// GraphNodeManager.h: Manager class for graph nodes.
//
//////////////////////////////////////////////////////////////////////
#ifndef __GRAPHNODEMANAGER_H__
#define __GRAPHNODEMANAGER_H__

//#include "GraphStructures.h"

class CGraphNodeManager
{
	enum { BUCKET_SIZE_SHIFT = 7 };
	enum { BUCKET_SIZE = 1 << BUCKET_SIZE_SHIFT };

public:
	CGraphNodeManager();
	~CGraphNodeManager();

	void Clear(unsigned typeMask);

	unsigned CreateNode(IAISystem::ENavigationType type, const Vec3 &pos, unsigned ID);
	void DestroyNode(unsigned index);

	GraphNode* GetNode(unsigned index)
	{
		if (index)
		{
			int bucket = (index - 1) >> BUCKET_SIZE_SHIFT;
			assert((bucket < m_buckets.size()) && "Corrupted node index!");
			BucketHeader* pBH = m_buckets[bucket];
			return pBH
				? reinterpret_cast<GraphNode*>(static_cast<char*>(pBH->nodes) +
					(((index - 1) & (BUCKET_SIZE - 1)) * pBH->nodeSize))
				: GetDummyNode();
		}
		return NULL;
	}

	const GraphNode* GetNode(unsigned index) const
	{
		if (index)
		{
			int bucket = (index - 1) >> BUCKET_SIZE_SHIFT;
			assert((bucket < m_buckets.size()) && "Corrupted node index!");
			BucketHeader* pBH = m_buckets[bucket];
			return pBH
				? reinterpret_cast<GraphNode*>(static_cast<char*>(pBH->nodes) +
					(((index - 1) & (BUCKET_SIZE - 1)) * pBH->nodeSize))
				: GetDummyNode();
		}
		return NULL;
	}

private:
	class BucketHeader
	{
	public:
		unsigned type;
		unsigned nodeSize;
		void* nodes;
	};

	// This function exists only to hide some fundamental problems in the path-finding system. Basically
	// things aren't cleaned up properly as of writing (pre-alpha Crysis 5/5/2007). Therefore we return
	// an object that looks like a graph node to stop client code from barfing.
	GraphNode* GetDummyNode() const;

	std::vector<BucketHeader*> m_buckets;

	// The number of the last bucket which contains nodes of the given type (index)
	// It is the bucket where a new node will be inserted (unless it's full)
	int m_lastBucket[IAISystem::NAV_TYPE_COUNT];

	// The index within the last bucket (see above), where the new node will be inserted
	int m_nextNode[IAISystem::NAV_TYPE_COUNT];

	int m_typeSizes[IAISystem::NAV_TYPE_COUNT];
};

#endif //__GRAPHNODEMANAGER_H__
